ouroboros git
FreeDVInterface.py HEAD (a5a8f2ed) Text, 36.75 KB
Tff7b72import T7ee787time
Tff7b72import T7ee787threading
Tff7b72import T7ee787queue
Tff7b72import T7ee787numpy Tff7b72as T7ee787np
Tff7b72import T7ee787pyaudio
Tff7b72from T7ee787ctypes Tff7b72import Tff7b72*
Tff7b72import T7ee787platform
Tff7b72import T7ee787math
Tff7b72from T7ee787threading Tff7b72import Te6edf3Lock
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787RNS
Tff7b72from T7ee787RNST7ee787.T7ee787InterfacesT7ee787.T7ee787Interface Tff7b72import Te6edf3Interface
Te6edf3MODE_DATAC1 Tff7b72= T79c0ff10
Te6edf3MODE_DATAC3 Tff7b72= T79c0ff12
Te6edf3MODE_DATAC4 Tff7b72= T79c0ff18
Tff7b72class T56d364FreeDVDataTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3modeTb4b4b4)Tb4b4b4:
Te6edf3system Tff7b72= Te6edf3platformTff7b72.Td2a8ffsystemTb4b4b4(Tb4b4b4)
Te6edf3libname Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffdebug Tff7b72= Tff7b72False
Tff7b72if Te6edf3system Tff7b72== Ta5d6ff'Ta5d6ffWindowsTa5d6ff'Tb4b4b4:
Te6edf3libname Tff7b72= Ta5d6ff'Ta5d6fflibcodec2.dllTa5d6ff'
Tff7b72elif Te6edf3system Tff7b72== Ta5d6ff'Ta5d6ffLinuxTa5d6ff'Tb4b4b4:
Te6edf3libname Tff7b72= Ta5d6ff'Ta5d6fflibcodec2.soTa5d6ff'
Tff7b72elif Te6edf3system Tff7b72== Ta5d6ff'Ta5d6ffDarwinTa5d6ff'Tb4b4b4:
Te6edf3libname Tff7b72= Ta5d6ff'Ta5d6fflibcodec2.dylibTa5d6ff'
Te6edf3lib_paths Tff7b72= Tb4b4b4[
Te6edf3libnameTb4b4b4,
Ta5d6fffTa5d6ff'Ta5d6ff./lib/Tffd700{Te6edf3libnameTffd700}Ta5d6ff'Tb4b4b4,
Ta5d6fffTa5d6ff'Ta5d6ff~/.reticulum/interfaces/lib/Tffd700{Te6edf3libnameTffd700}Ta5d6ff'Tb4b4b4,
Ta5d6fffTa5d6ff'Ta5d6ff/usr/local/lib/Tffd700{Te6edf3libnameTffd700}Ta5d6ff'Tb4b4b4,
Ta5d6fffTa5d6ff'Ta5d6ff/usr/lib/Tffd700{Te6edf3libnameTffd700}Ta5d6ff'Tb4b4b4,
Tb4b4b4]
Te6edf3loaded Tff7b72= Tff7b72False
Tff7b72for Te6edf3path Tff7b72in Te6edf3lib_pathsTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffc_lib Tff7b72= Te6edf3CDLLTb4b4b4(Te6edf3pathTb4b4b4)
Te6edf3loaded Tff7b72= Tff7b72True
Tff7b72break
Tff7b72exceptTb4b4b4:
Tff7b72continue
Tff7b72if Tff7b72not Te6edf3loadedTb4b4b4:
Tff7b72raise Tf85149ExceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCould not load FreeDV library. Tried paths: Tffd700{Te6edf3lib_pathsTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmode Tff7b72= Te6edf3mode
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_openTff7b72.Td2a8ffrestype Tff7b72= Te6edf3POINTERTb4b4b4(Te6edf3c_ubyteTb4b4b4)
Tff7b72selfTff7b72.Td2a8fffreedv Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_openTb4b4b4(Te6edf3modeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_max_modem_samplesTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_max_modem_samplesTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_modem_samplesTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_modem_samplesTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_size_t
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_preamble_modem_samplesTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_preamble_modem_samplesTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_size_t
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_postamble_modem_samplesTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_postamble_modem_samplesTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_size_t
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_bits_per_modem_frameTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_bits_per_modem_frameTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_size_t
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_ninTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_ninTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatarxTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatarxTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapreambletxTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapreambletxTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatatxTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatatxTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_void_p
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapostambletxTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapostambletxTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_gen_crc16Tff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_size_tTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_gen_crc16Tff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_uint16
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_frames_per_burstTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_intTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_frames_per_burstTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_void_p
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_verboseTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3c_intTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_verboseTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_void_p
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_closeTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_closeTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_void_p
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_syncTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_syncTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_rx_statusTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_rx_statusTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_sample_rateTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_sample_rateTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_nom_modem_samplesTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_nom_modem_samplesTff7b72.Td2a8ffrestype Tff7b72= Te6edf3c_int
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_statsTff7b72.Td2a8ffargtypes Tff7b72= Tb4b4b4[Te6edf3c_void_pTb4b4b4, Te6edf3POINTERTb4b4b4(Te6edf3c_intTb4b4b4)Tb4b4b4, Te6edf3POINTERTb4b4b4(Te6edf3c_floatTb4b4b4)Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_statsTff7b72.Td2a8ffrestype Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffbytes_per_modem_frame Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_bits_per_modem_frameTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4) Tff7b72/Tff7b72/ T79c0ff8
Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frame Tff7b72= Tff7b72selfTff7b72.Td2a8ffbytes_per_modem_frame Tff7b72- T79c0ff2
Tff7b72selfTff7b72.Td2a8ffn_mod_out Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_modem_samplesTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffn_tx_modem_samples Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_modem_samplesTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffn_tx_preamble_modem_samples Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_preamble_modem_samplesTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffn_tx_postamble_modem_samples Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_tx_postamble_modem_samplesTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_frames_per_burstTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, T79c0ff1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_set_verboseTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnin Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_freedv_rx_ninTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8fftx_burstTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3data_inTb4b4b4)Tb4b4b4:
Te6edf3num_frames Tff7b72= Te6edf3mathTff7b72.Td2a8ffceilTb4b4b4(Tffa657lenTb4b4b4(Te6edf3data_inTb4b4b4) Tff7b72/ Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frameTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV modem TX: Tffd700{Tffa657lenTb4b4b4(Te6edf3data_inTb4b4b4)Tffd700}Ta5d6ff bytes in Tffd700{Te6edf3num_framesTffd700}Ta5d6ff framesTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_EXTREMETb4b4b4)
Te6edf3mod_out Tff7b72= Te6edf3create_string_bufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffn_tx_modem_samples Tff7b72* T79c0ff2Tb4b4b4)
Te6edf3mod_out_preamble Tff7b72= Te6edf3create_string_bufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffn_tx_preamble_modem_samples Tff7b72* T79c0ff2Tb4b4b4)
Te6edf3mod_out_postamble Tff7b72= Te6edf3create_string_bufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffn_tx_postamble_modem_samples Tff7b72* T79c0ff2Tb4b4b4)
T8b949e# Preamble
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapreambletxTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3mod_out_preambleTb4b4b4)
Te6edf3txbuffer Tff7b72= Tffa657bytesTb4b4b4(Te6edf3mod_out_preambleTb4b4b4)
T8b949e# Create data frames
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3num_framesTb4b4b4)Tb4b4b4:
T8b949e# Main data buffer
Te6edf3buffer Tff7b72= Tffa657bytearrayTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frameTb4b4b4)
Te6edf3data_chunk Tff7b72= Te6edf3data_inTb4b4b4[Te6edf3i Tff7b72* Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frameTb4b4b4:Tb4b4b4(Te6edf3i Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72* Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frameTb4b4b4]
Te6edf3bufferTb4b4b4[Tb4b4b4:Tffa657lenTb4b4b4(Te6edf3data_chunkTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3data_chunk
T8b949e# Add CRC16
Te6edf3crc16 Tff7b72= Te6edf3c_ushortTb4b4b4(Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_gen_crc16Tb4b4b4(Tffa657bytesTb4b4b4(Te6edf3bufferTb4b4b4)Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffpayload_bytes_per_modem_frameTb4b4b4)Tb4b4b4)
Te6edf3crc16 Tff7b72= Te6edf3crc16Tff7b72.Td2a8ffvalueTff7b72.Td2a8ffto_bytesTb4b4b4(T79c0ff2Tb4b4b4, Te6edf3byteorderTff7b72=Ta5d6ff'Ta5d6ffbigTa5d6ff'Tb4b4b4)
Te6edf3buffer Tff7b72+Tff7b72= Te6edf3crc16
Te6edf3data Tff7b72= Tb4b4b4(Te6edf3c_ubyte Tff7b72* Tff7b72selfTff7b72.Td2a8ffbytes_per_modem_frameTb4b4b4)Tff7b72.Td2a8fffrom_buffer_copyTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatatxTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3mod_outTb4b4b4, Te6edf3dataTb4b4b4)
Te6edf3txbuffer Tff7b72+Tff7b72= Tffa657bytesTb4b4b4(Te6edf3mod_outTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatapostambletxTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3mod_out_postambleTb4b4b4)
Te6edf3txbuffer Tff7b72+Tff7b72= Te6edf3mod_out_postamble
Te6edf3s_multiplier Tff7b72= T79c0ff2
Te6edf3silence_samples Tff7b72= Tffa657intTb4b4b4(Tb4b4b4(T79c0ff100 Tff7b72/ T79c0ff1000Tb4b4b4) Tff7b72* T79c0ff8000Tb4b4b4) Tff7b72* Te6edf3s_multiplier
Te6edf3txbuffer Tff7b72+Tff7b72= Tffa657bytesTb4b4b4(Te6edf3silence_samplesTb4b4b4)
T8b949e# extra_silence = self.c_lib.freedv_get_n_nom_modem_samples(self.freedv) * 2 * 2
T8b949e# txbuffer += bytes(extra_silence)
Tff7b72return Te6edf3txbuffer
Tff7b72def Td2a8ffget_freedv_rx_ninTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_ninTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72def Td2a8ffget_modem_sample_rateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_sample_rateTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72def Td2a8ffget_n_nom_modem_samplesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_n_nom_modem_samplesTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72def Td2a8ffget_syncTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3sync Tff7b72= Te6edf3c_intTb4b4b4(Tb4b4b4)
Te6edf3snr Tff7b72= Te6edf3c_floatTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_statsTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3byrefTb4b4b4(Te6edf3syncTb4b4b4)Tb4b4b4, Te6edf3byrefTb4b4b4(Te6edf3snrTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3syncTff7b72.Td2a8ffvalue
Tff7b72def Td2a8ffget_rx_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_rx_statusTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72def Td2a8ffrxTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3demod_inTb4b4b4)Tb4b4b4:
Te6edf3bytes_out Tff7b72= Te6edf3create_string_bufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbytes_per_modem_frameTb4b4b4)
Te6edf3nbytes_out Tff7b72= Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_rawdatarxTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3bytes_outTb4b4b4, Te6edf3demod_inTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnin Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_freedv_rx_ninTb4b4b4(Tb4b4b4)
T8b949e# get FreeDV modem stats
Te6edf3sync Tff7b72= Te6edf3c_intTb4b4b4(Tb4b4b4)
Te6edf3snr Tff7b72= Te6edf3c_floatTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_get_modem_statsTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4, Te6edf3byrefTb4b4b4(Te6edf3syncTb4b4b4)Tb4b4b4, Te6edf3byrefTb4b4b4(Te6edf3snrTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3nbytes_outTb4b4b4, Te6edf3bytes_outTb4b4b4[Tb4b4b4:Te6edf3nbytes_outTb4b4b4]Tb4b4b4, Te6edf3syncTff7b72.Td2a8ffvalueTb4b4b4, Te6edf3snrTff7b72.Td2a8ffvalue
Tff7b72def Td2a8ffcloseTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffc_libTff7b72.Td2a8fffreedv_closeTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedvTb4b4b4)
Tff7b72class T56d364AudioBufferTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsize Tff7b72= Te6edf3size
Tff7b72selfTff7b72.Td2a8ffbuffer Tff7b72= Te6edf3npTff7b72.Td2a8ffzerosTb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3dtypeTff7b72=Te6edf3npTff7b72.Td2a8ffint16Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffmutex Tff7b72= Te6edf3LockTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffpushTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3samplesTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3space_available Tff7b72= Tff7b72selfTff7b72.Td2a8ffsize Tff7b72- Tff7b72selfTff7b72.Td2a8ffnbuffer
Tff7b72if Tffa657lenTb4b4b4(Te6edf3samplesTb4b4b4) Tff7b72> Te6edf3space_availableTb4b4b4:
Te6edf3samples_to_drop Tff7b72= Tffa657lenTb4b4b4(Te6edf3samplesTb4b4b4) Tff7b72- Te6edf3space_available
Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Tb4b4b4:Tff7b72-Te6edf3samples_to_dropTb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Te6edf3samples_to_dropTb4b4b4:Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72-Tff7b72= Te6edf3samples_to_drop
Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Tff7b72selfTff7b72.Td2a8ffnbufferTb4b4b4: Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72+ Tffa657lenTb4b4b4(Te6edf3samplesTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3samples
Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3samplesTb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffpopTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3size Tff7b72> Tff7b72selfTff7b72.Td2a8ffnbufferTb4b4b4:
Te6edf3size Tff7b72= Tff7b72selfTff7b72.Td2a8ffnbuffer
Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72-Tff7b72= Te6edf3size
Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnbufferTb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Te6edf3sizeTb4b4b4: Te6edf3size Tff7b72+ Tff7b72selfTff7b72.Td2a8ffnbufferTb4b4b4]
Tff7b72finallyTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffget_samplesTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffnbuffer Tff7b72>Tff7b72= Te6edf3sizeTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4[Tb4b4b4:Te6edf3sizeTb4b4b4]Tff7b72.Td2a8ffcopyTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72None
Tff7b72finallyTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmutexTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72class T56d364FreeDVInterfaceTb4b4b4(Te6edf3InterfaceTb4b4b4)Tb4b4b4:
Te6edf3DEFAULT_IFAC_SIZE Tff7b72= T79c0ff8
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ownerTb4b4b4, Te6edf3configurationTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Tb4b4b4)
T8b949e# Parse configuration
Te6edf3ifconf Tff7b72= Te6edf3InterfaceTff7b72.Td2a8ffget_config_objTb4b4b4(Te6edf3configurationTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffname Tff7b72= Te6edf3ifconfTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffdebug Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdebugTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffalseTa5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6fftrueTa5d6ff"
T8b949e# Get configuration parameters
Tff7b72selfTff7b72.Td2a8ffinput_device_config Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinput_deviceTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffoutput_device_config Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoutput_deviceTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinput_device Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_device_indexTb4b4b4(Tff7b72selfTff7b72.Td2a8ffinput_device_configTb4b4b4, Te6edf3is_inputTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffoutput_device Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_device_indexTb4b4b4(Tff7b72selfTff7b72.Td2a8ffoutput_device_configTb4b4b4, Te6edf3is_inputTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72selfTff7b72.Td2a8fffreedv_mode_str Tff7b72= Te6edf3ifconfTb4b4b4[Ta5d6ff"Ta5d6fffreedv_modeTa5d6ff"Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72if Ta5d6ff"Ta5d6fffreedv_modeTa5d6ff" Tff7b72in Te6edf3ifconf Tff7b72else Ta5d6ff"Ta5d6ffdatac1Ta5d6ff"
Tff7b72selfTff7b72.Td2a8fftx_volume Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftx_volumeTa5d6ff"Tb4b4b4, T79c0ff100Tb4b4b4)Tb4b4b4) Tff7b72/ T79c0ff100.0
T8b949e# PTT configuration
Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnoneTa5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) T8b949e# none, serial, hamlib, vox
Tff7b72selfTff7b72.Td2a8ffptt_enabled Tff7b72= Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72!= Ta5d6ff"Ta5d6ffnoneTa5d6ff"
T8b949e# serial PTT settings
Tff7b72selfTff7b72.Td2a8ffptt_port Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_portTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptt_serial_type Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_serial_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffDTRTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
T8b949e# Hamlib settings
Tff7b72selfTff7b72.Td2a8ffhamlib_model Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_modelTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4) T8b949e# 1 = dummy/test
Tff7b72selfTff7b72.Td2a8ffhamlib_device Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_deviceTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/dev/ttyUSB0Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_rigctl Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_rigctlTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrigctlTa5d6ff"Tb4b4b4) T8b949e# path to rigctl
Tff7b72selfTff7b72.Td2a8ffhamlib_speed Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_speedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff19200Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_data_bits Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_data_bitsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff8Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_stop_bits Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_stop_bitsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_parity Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_parityTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffNTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_extra_args Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_extra_argsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_network Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_networkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffalseTa5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6fftrueTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffhamlib_host Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_hostTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflocalhostTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhamlib_port Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhamlib_portTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff4532Ta5d6ff"Tb4b4b4)
T8b949e# PTT timing
Tff7b72selfTff7b72.Td2a8ffptt_on_delay Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_on_delayTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.1Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# Delay after PTT on
Tff7b72selfTff7b72.Td2a8ffptt_off_delay Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_off_delayTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.1Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# Delay before PTT off
Tff7b72selfTff7b72.Td2a8ffptt_tail_delay Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffptt_tail_delayTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.1Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# Delay after PTT off
Tff7b72selfTff7b72.Td2a8ffvox_delay Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffvox_delayTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.5Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# Extra delay for VOX activation
Tff7b72selfTff7b72.Td2a8ffvox_tone Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffvox_toneTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffalseTa5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6fftrueTa5d6ff" T8b949e# Send tone for VOX activation
T8b949e# Set FreeDV mode
Tff7b72if Tff7b72selfTff7b72.Td2a8fffreedv_mode_str Tff7b72== Ta5d6ff"Ta5d6ffdatac3Ta5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fffreedv_mode Tff7b72= Te6edf3MODE_DATAC3
Tff7b72selfTff7b72.Td2a8ffHW_MTU Tff7b72= T79c0ff508 T8b949e# temp
Tff7b72selfTff7b72.Td2a8ffbitrate Tff7b72= T79c0ff250
Tff7b72raise Tf85149NotImplementedError
Tff7b72elif Tff7b72selfTff7b72.Td2a8fffreedv_mode_str Tff7b72== Ta5d6ff"Ta5d6ffdatac4Ta5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fffreedv_mode Tff7b72= Te6edf3MODE_DATAC4
Tff7b72selfTff7b72.Td2a8ffHW_MTU Tff7b72= T79c0ff508 T8b949e# temp
Tff7b72selfTff7b72.Td2a8ffbitrate Tff7b72= T79c0ff125
Tff7b72raise Tf85149NotImplementedError
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8fffreedv_mode Tff7b72= Te6edf3MODE_DATAC1
Tff7b72selfTff7b72.Td2a8ffHW_MTU Tff7b72= T79c0ff508 T8b949e# temp
Tff7b72selfTff7b72.Td2a8ffbitrate Tff7b72= T79c0ff980
T8b949e# Initialize properties
Tff7b72selfTff7b72.Td2a8ffonline Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffowner Tff7b72= Te6edf3owner
Tff7b72selfTff7b72.Td2a8ffaudio_frames_per_buffer Tff7b72= T79c0ff256
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72False
T8b949e# Channel state for CSMA
Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8fflast_sync_time Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffsync_lock Tff7b72= Te6edf3LockTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsignal_threshold Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsignal_thresholdTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.35Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# 0-1 normalized
Tff7b72selfTff7b72.Td2a8ffrecent_signal_level Tff7b72= T79c0ff0.0
T8b949e# CSMA settings
Tff7b72selfTff7b72.Td2a8ffcsma_enabled Tff7b72= Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcsma_enabledTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftrueTa5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6fftrueTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffcsma_wait_time Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcsma_wait_timeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff2.0Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# wait time after channel busy
Tff7b72selfTff7b72.Td2a8ffchannel_busy_timeout Tff7b72= Tffa657floatTb4b4b4(
Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffchannel_busy_timeoutTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.5Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# time after last activity before channel is clear
Tff7b72selfTff7b72.Td2a8ffsignal_threshold Tff7b72= Tffa657floatTb4b4b4(Te6edf3ifconfTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsignal_thresholdTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0.1Ta5d6ff"Tb4b4b4)Tb4b4b4) T8b949e# audio level threshold
Tff7b72selfTff7b72.Td2a8fftx_queue Tff7b72= Te6edf3queueTff7b72.Td2a8ffQueueTb4b4b4(Te6edf3maxsizeTff7b72=T79c0ff100Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrx_queue Tff7b72= Te6edf3queueTff7b72.Td2a8ffQueueTb4b4b4(Tb4b4b4)
T8b949e# audio buffers
Tff7b72selfTff7b72.Td2a8ffrx_audio_buffer Tff7b72= Te6edf3AudioBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffaudio_frames_per_buffer Tff7b72* T79c0ff10000Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fftx_audio_buffer Tff7b72= Te6edf3AudioBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ffaudio_frames_per_buffer Tff7b72* T79c0ff10000Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8fftx_thread Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffrx_thread Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffaudio_thread Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffmonitor_thread Tff7b72= Tff7b72None
T8b949e# PTT handling
Tff7b72selfTff7b72.Td2a8ffptt_serial Tff7b72= Tff7b72None
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffserialTa5d6ff" Tff7b72and Tff7b72selfTff7b72.Td2a8ffptt_portTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72import T7ee787serial
Tff7b72selfTff7b72.Td2a8ffptt_serial Tff7b72= Te6edf3serialTff7b72.Td2a8ffSerialTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptt_portTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffSerial PTT enabled on Tffd700{Tff7b72selfTff7b72.Td2a8ffptt_portTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCould not open PTT port Tffd700{Tff7b72selfTff7b72.Td2a8ffptt_portTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptt_enabled Tff7b72= Tff7b72False
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffhamlibTa5d6ff"Tb4b4b4:
T8b949e# Check if rigctl exists
Tff7b72tryTb4b4b4:
Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffhamlib_rigctlTb4b4b4, Ta5d6ff"Ta5d6ff-VTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72except Tb4b4b4(Te6edf3subprocessTff7b72.Td2a8ffTimeoutExpiredTb4b4b4, Tf85149FileNotFoundErrorTb4b4b4) Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffrigctl not found or not working: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptt_enabled Tff7b72= Tff7b72False
Tff7b72return
T8b949e# Test hamlib connection
Tff7b72if Tff7b72selfTff7b72.Td2a8fftest_hamlibTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib PTT enabled - Model: Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_modelTffd700}Ta5d6ff, Device: Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_deviceTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffHamlib PTT test failed - check configurationTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptt_enabled Tff7b72= Tff7b72False
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffvoxTa5d6ff"Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffVOX PTT enabled with Tffd700{Tff7b72selfTff7b72.Td2a8ffvox_delayTffd700}Ta5d6ffs activation delayTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
T8b949e# start our threads
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8fffreedv Tff7b72= Te6edf3FreeDVDataTb4b4b4(Tff7b72selfTff7b72.Td2a8fffreedv_modeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinit_audioTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstart_threadsTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffonline Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffmonitor_thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffmonitor_loopTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmonitor_threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV Interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] is online using Tffd700{Tff7b72selfTff7b72.Td2a8fffreedv_mode_strTff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff MTU: Tffd700{Tff7b72selfTff7b72.Td2a8ffHW_MTUTffd700}Ta5d6ff bytes, Bitrate: ~Tffd700{Tff7b72selfTff7b72.Td2a8ffbitrateTffd700}Ta5d6ff bpsTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Mode: Tffd700{Tff7b72selfTff7b72.Td2a8fffreedvTffd700}Ta5d6ff, Payload/frame: Tffd700{Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffpayload_bytes_per_modem_frameTffd700}Ta5d6ff bytesTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffcsma_enabledTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff CSMA: Enabled (wait=Tffd700{Tff7b72selfTff7b72.Td2a8ffcsma_wait_timeTffd700}Ta5d6ffs, timeout=Tffd700{Tff7b72selfTff7b72.Td2a8ffchannel_busy_timeoutTffd700}Ta5d6ffs)Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff CSMA: DisabledTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_enabledTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffhamlibTa5d6ff"Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhamlib_networkTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff PTT: Hamlib network mode (Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_hostTffd700}Ta5d6ff:Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_portTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff PTT: Hamlib model Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_modelTffd700}Ta5d6ff on Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_deviceTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffserialTa5d6ff"Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff PTT: Serial Tffd700{Tff7b72selfTff7b72.Td2a8ffptt_serial_typeTffd700}Ta5d6ff on Tffd700{Tff7b72selfTff7b72.Td2a8ffptt_portTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffvoxTa5d6ff"Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff PTT: VOX with Tffd700{Tff7b72selfTff7b72.Td2a8ffvox_delayTffd700}Ta5d6ffs delayTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCould not initialize FreeDV interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72raise Te6edf3e
Tff7b72def Td2a8ffget_device_indexTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3device_configTb4b4b4, Te6edf3is_inputTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3device_configTb4b4b4, Tffa657intTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3device_config
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3device_configTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72pass
Te6edf3p Tff7b72= Te6edf3pyaudioTff7b72.Td2a8ffPyAudioTb4b4b4(Tb4b4b4)
Te6edf3device_index Tff7b72= Tff7b72None
Te6edf3search_name Tff7b72= Te6edf3device_configTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3pTff7b72.Td2a8ffget_device_countTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3info Tff7b72= Te6edf3pTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Te6edf3iTb4b4b4)
Te6edf3device_name Tff7b72= Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3is_input Tff7b72and Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxInputChannelsTa5d6ff'Tb4b4b4] Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72continue
Tff7b72if Tff7b72not Te6edf3is_input Tff7b72and Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxOutputChannelsTa5d6ff'Tb4b4b4] Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3device_name Tff7b72== Te6edf3search_nameTb4b4b4:
Te6edf3device_index Tff7b72= Te6edf3i
Tff7b72break
T8b949e# partial match
Tff7b72if Te6edf3search_name Tff7b72in Te6edf3device_nameTb4b4b4:
Te6edf3device_index Tff7b72= Te6edf3i
Te6edf3pTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3device_index Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCould not find audio device Ta5d6ff'Tffd700{Te6edf3device_configTffd700}Ta5d6ff'Ta5d6ff for Tffd700{Ta5d6ff'Ta5d6ffinputTa5d6ff' Tff7b72if Te6edf3is_input Tff7b72else Ta5d6ff'Ta5d6ffoutputTa5d6ff'Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffAvailable devices:Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3p Tff7b72= Te6edf3pyaudioTff7b72.Td2a8ffPyAudioTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3pTff7b72.Td2a8ffget_device_countTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3info Tff7b72= Te6edf3pTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Te6edf3iTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3is_input Tff7b72and Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxInputChannelsTa5d6ff'Tb4b4b4] Tff7b72> T79c0ff0Tb4b4b4) Tff7b72or Tb4b4b4(Tff7b72not Te6edf3is_input Tff7b72and Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxOutputChannelsTa5d6ff'Tb4b4b4] Tff7b72> T79c0ff0Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Tffd700{Te6edf3iTffd700}Ta5d6ff: Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3pTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffAudio device Ta5d6ff'Tffd700{Te6edf3device_configTffd700}Ta5d6ff'Ta5d6ff not foundTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3p Tff7b72= Te6edf3pyaudioTff7b72.Td2a8ffPyAudioTb4b4b4(Tb4b4b4)
Te6edf3info Tff7b72= Te6edf3pTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Te6edf3device_indexTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffFound Tffd700{Ta5d6ff'Ta5d6ffinputTa5d6ff' Tff7b72if Te6edf3is_input Tff7b72else Ta5d6ff'Ta5d6ffoutputTa5d6ff'Tffd700}Ta5d6ff device Ta5d6ff'Tffd700{Te6edf3device_configTffd700}Ta5d6ff'Ta5d6ff at index Tffd700{Te6edf3device_indexTffd700}Ta5d6ff: Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3pTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3device_index
Tff7b72def Td2a8ffinit_audioTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffp Tff7b72= Te6edf3pyaudioTff7b72.Td2a8ffPyAudioTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInitializing audio for FreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3input_info Tff7b72= Tff7b72selfTff7b72.Td2a8ffpTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Tff7b72selfTff7b72.Td2a8ffinput_deviceTb4b4b4)
Te6edf3output_info Tff7b72= Tff7b72selfTff7b72.Td2a8ffpTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Tff7b72selfTff7b72.Td2a8ffoutput_deviceTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInput device: Tffd700{Tff7b72selfTff7b72.Td2a8ffinput_deviceTffd700}Ta5d6ff (Tffd700{Te6edf3input_infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffOutput device: Tffd700{Tff7b72selfTff7b72.Td2a8ffoutput_deviceTffd700}Ta5d6ff (Tffd700{Te6edf3output_infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72tryTb4b4b4:
T8b949e# Open audio stream
Tff7b72selfTff7b72.Td2a8ffstream Tff7b72= Tff7b72selfTff7b72.Td2a8ffpTff7b72.Td2a8ffopenTb4b4b4(
Te6edf3rateTff7b72=T79c0ff8000Tb4b4b4,
Te6edf3channelsTff7b72=T79c0ff1Tb4b4b4,
Tffa657formatTff7b72=Te6edf3pyaudioTff7b72.Td2a8ffpaInt16Tb4b4b4,
Te6edf3frames_per_bufferTff7b72=Tff7b72selfTff7b72.Td2a8ffaudio_frames_per_bufferTb4b4b4,
Tffa657inputTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3outputTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3input_device_indexTff7b72=Tff7b72selfTff7b72.Td2a8ffinput_deviceTb4b4b4,
Te6edf3output_device_indexTff7b72=Tff7b72selfTff7b72.Td2a8ffoutput_deviceTb4b4b4,
Te6edf3stream_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ffaudio_callback
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffstart_streamTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffis_activeTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffAudio stream failed to start - check configurationTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffAudio stream started [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed audio | [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72raise
Tff7b72def Td2a8ffaudio_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3in_dataTb4b4b4, Te6edf3frame_countTb4b4b4, Te6edf3time_infoTb4b4b4, Te6edf3statusTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# always capture input audio
Te6edf3samples_int16 Tff7b72= Te6edf3npTff7b72.Td2a8fffrombufferTb4b4b4(Te6edf3in_dataTb4b4b4, Te6edf3dtypeTff7b72=Te6edf3npTff7b72.Td2a8ffint16Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffpushTb4b4b4(Te6edf3samples_int16Tb4b4b4)
T8b949e# check if we have TX audio to send
Tff7b72if Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffnbuffer Tff7b72>Tff7b72= Te6edf3frame_countTb4b4b4:
Te6edf3tx_samples Tff7b72= Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffbufferTb4b4b4[Tb4b4b4:Te6edf3frame_countTb4b4b4]Tff7b72.Td2a8ffcopyTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffpopTb4b4b4(Te6edf3frame_countTb4b4b4)
T8b949e# TODO
Te6edf3tx_samples Tff7b72= Tb4b4b4(Te6edf3tx_samples Tff7b72* Tff7b72selfTff7b72.Td2a8fftx_volumeTb4b4b4)Tff7b72.Td2a8ffastypeTb4b4b4(Te6edf3npTff7b72.Td2a8ffint16Tb4b4b4)
Tff7b72return Te6edf3tx_samplesTff7b72.Td2a8fftobytesTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3pyaudioTff7b72.Td2a8ffpaContinue
Tff7b72return Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Tb4b4b4(Te6edf3frame_count Tff7b72* T79c0ff2Tb4b4b4)Tb4b4b4, Te6edf3pyaudioTff7b72.Td2a8ffpaContinue
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffAudio callback error [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72return Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Tb4b4b4(Te6edf3frame_count Tff7b72* T79c0ff2Tb4b4b4)Tb4b4b4, Te6edf3pyaudioTff7b72.Td2a8ffpaContinue
Tff7b72def Td2a8ffstart_threadsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Start processing threads"""
Tff7b72selfTff7b72.Td2a8fftx_thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8fftx_loopTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrx_thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffrx_loopTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8fftx_threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrx_threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffbuild_hamlib_cmdTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3cmd Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffhamlib_rigctlTb4b4b4]
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhamlib_networkTb4b4b4:
T8b949e# network mode
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-mTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff2Ta5d6ff"Tb4b4b4]Tb4b4b4) T8b949e# 2 = NET rigctl
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-rTa5d6ff"Tb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_hostTffd700}Ta5d6ff:Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_portTffd700}Ta5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# direct serial mode
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-mTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffhamlib_modelTb4b4b4]Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-rTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffhamlib_deviceTb4b4b4]Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-sTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffhamlib_speedTb4b4b4]Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-CTa5d6ff"Tb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffdata_bits=Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_data_bitsTffd700}Ta5d6ff"Tb4b4b4]Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-CTa5d6ff"Tb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffstop_bits=Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_stop_bitsTffd700}Ta5d6ff"Tb4b4b4]Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-CTa5d6ff"Tb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffserial_parity=Tffd700{Tff7b72selfTff7b72.Td2a8ffhamlib_parityTffd700}Ta5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhamlib_extra_argsTb4b4b4:
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tff7b72selfTff7b72.Td2a8ffhamlib_extra_argsTff7b72.Td2a8ffsplitTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3cmd
Tff7b72def Td2a8fftest_hamlibTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3cmd Tff7b72= Tff7b72selfTff7b72.Td2a8ffbuild_hamlib_cmdTb4b4b4(Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6fffTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffTesting hamlib with command: Tffd700{Ta5d6ff'Ta5d6ff Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cmdTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3textTff7b72=Tff7b72TrueTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebug Tff7b72and Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib test output: Tffd700{Te6edf3resultTff7b72.Td2a8ffstderrTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72== T79c0ff0
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib test failed: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffptt_onTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffptt_enabledTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffvoxTa5d6ff"Tb4b4b4:
T8b949e# For VOX, just add extra delay for VOX circuit to activate
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffvox_delayTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffserialTa5d6ff" Tff7b72and Tff7b72selfTff7b72.Td2a8ffptt_serialTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_serial_type Tff7b72== Ta5d6ff"Ta5d6ffDTRTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffptt_serialTff7b72.Td2a8ffdtr Tff7b72= Tff7b72True
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_serial_type Tff7b72== Ta5d6ff"Ta5d6ffRTSTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffptt_serialTff7b72.Td2a8ffrts Tff7b72= Tff7b72True
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptt_on_delayTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffhamlibTa5d6ff"Tb4b4b4:
Te6edf3cmd Tff7b72= Tff7b72selfTff7b72.Td2a8ffbuild_hamlib_cmdTb4b4b4(Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ffTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4]Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3textTff7b72=Tff7b72TrueTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0 Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib PTT ON failed: Tffd700{Te6edf3resultTff7b72.Td2a8ffstderrTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptt_on_delayTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib PTT ONTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPTT control error: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72def Td2a8ffptt_offTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffptt_enabledTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffvoxTa5d6ff"Tb4b4b4:
T8b949e#
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptt_off_delayTb4b4b4) T8b949e# PTT delay before off
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffserialTa5d6ff" Tff7b72and Tff7b72selfTff7b72.Td2a8ffptt_serialTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_serial_type Tff7b72== Ta5d6ff"Ta5d6ffDTRTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffptt_serialTff7b72.Td2a8ffdtr Tff7b72= Tff7b72False
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_serial_type Tff7b72== Ta5d6ff"Ta5d6ffRTSTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffptt_serialTff7b72.Td2a8ffrts Tff7b72= Tff7b72False
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffhamlibTa5d6ff"Tb4b4b4:
Te6edf3cmd Tff7b72= Tff7b72selfTff7b72.Td2a8ffbuild_hamlib_cmdTb4b4b4(Tb4b4b4)
Te6edf3cmdTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ffTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff0Ta5d6ff"Tb4b4b4]Tb4b4b4) T8b949e# PTT off command
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3textTff7b72=Tff7b72TrueTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0 Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib PTT OFF failed: Tffd700{Te6edf3resultTff7b72.Td2a8ffstderrTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHamlib PTT OFFTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPTT control error: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72def Td2a8ffmonitor_loopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3last_log Tff7b72= T79c0ff0
Tff7b72while Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3now Tff7b72- Te6edf3last_log Tff7b72> T79c0ff30 Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] status: TX queue=Tffd700{Tff7b72selfTff7b72.Td2a8fftx_queueTff7b72.Td2a8ffqsizeTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff, Ta5d6ff" Tff7b72+
Ta5d6fffTa5d6ff"Ta5d6ffRX buffer=Tffd700{Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffnbufferTffd700}Ta5d6ff, TX buffer=Tffd700{Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffnbufferTffd700}Ta5d6ff, Ta5d6ff" Tff7b72+
Ta5d6fffTa5d6ff"Ta5d6ffTransmitting=Tffd700{Tff7b72selfTff7b72.Td2a8ffis_transmittingTffd700}Ta5d6ff, Channel busy=Tffd700{Tff7b72selfTff7b72.Td2a8ffchannel_busyTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3last_log Tff7b72= Te6edf3now
T8b949e# check if our audio stream is still active
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffstreamTa5d6ff'Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffstream Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffis_activeTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffAudio stream died on FreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff], attempting restartTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffonline Tff7b72= Tff7b72False
Tff7b72break
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffMonitor error in FreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72def Td2a8ffupdate_channel_stateTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3has_syncTb4b4b4, Te6edf3signal_levelTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffsync_lockTb4b4b4:
Tff7b72if Te6edf3signal_level Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrecent_signal_level Tff7b72= Te6edf3signal_level
T8b949e# channel is busy if we have sync OR signal level is above threshold
Tff7b72if Te6edf3has_sync Tff7b72or Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffrecent_signal_level Tff7b72> Tff7b72selfTff7b72.Td2a8ffsignal_thresholdTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8fflast_sync_time Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebug Tff7b72and Tb4b4b4(Te6edf3has_sync Tff7b72or Tff7b72selfTff7b72.Td2a8ffrecent_signal_level Tff7b72> Tff7b72selfTff7b72.Td2a8ffsignal_thresholdTb4b4b4)Tb4b4b4:
Te6edf3reason Tff7b72= Ta5d6ff"Ta5d6ffsync detectedTa5d6ff" Tff7b72if Te6edf3has_sync Tff7b72else Ta5d6fffTa5d6ff"Ta5d6ffsignal level Tffd700{Tff7b72selfTff7b72.Td2a8ffrecent_signal_levelTffd700:Ta5d6ff.3fTffd700}Ta5d6ff"
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] channel busy - Tffd700{Te6edf3reasonTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# channel is considered free if no sync/signal above threshold for timeout period
Tff7b72if Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8fflast_sync_time Tff7b72> Tff7b72selfTff7b72.Td2a8ffchannel_busy_timeoutTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] channel now clearTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72= Tff7b72False
Tff7b72def Td2a8ffis_channel_clearTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffsync_lockTb4b4b4:
T8b949e# also check if RX buffer has significant data (someone might be transmitting)
Te6edf3rx_buffer_busy Tff7b72= Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffnbuffer Tff7b72> Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffaudio_frames_per_buffer Tff7b72* T79c0ff10Tb4b4b4)
Tff7b72if Te6edf3rx_buffer_busy Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] channel busy - RX buffer has Tffd700{Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffnbufferTffd700}Ta5d6ff samplesTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Tff7b72not Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72and Tff7b72not Te6edf3rx_buffer_busy
Tff7b72def Td2a8ffwait_for_clear_channelTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffcsma_enabledTb4b4b4:
Tff7b72return Tff7b72True
T8b949e# check if channel is already clear
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_channel_clearTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] channel clear, transmittingTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Tff7b72True
T8b949e# Channel is busy, wait for it to clear
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] channel busy, waiting...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3wait_start Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3last_log Tff7b72= Te6edf3wait_start
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ffis_channel_clearTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4) T8b949e# Check every 100ms
T8b949e# log every 5 seconds while waiting
Tff7b72if Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3last_log Tff7b72> T79c0ff5.0Tb4b4b4:
Te6edf3wait_time Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3wait_start
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] still waiting for clear channel (Tffd700{Te6edf3wait_timeTffd700:Ta5d6ff.1fTffd700}Ta5d6ffs)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3last_log Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffcsma_wait_timeTb4b4b4)
T8b949e# check one more time that channel is still clear
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffis_channel_clearTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffwait_for_clear_channelTb4b4b4(Tb4b4b4)
Te6edf3total_wait Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3wait_start
Tff7b72if Te6edf3total_wait Tff7b72> T79c0ff0.5Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffchannel clear after Tffd700{Te6edf3total_waitTffd700:Ta5d6ff.1fTffd700}Ta5d6ffs, transmittingTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72def Td2a8fftx_loopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72while Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3packet Tff7b72= Tff7b72selfTff7b72.Td2a8fftx_queueTff7b72.Td2a8ffgetTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff0.1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwait_for_clear_channelTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72True
Te6edf3max_payload Tff7b72= Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffpayload_bytes_per_modem_frame
Tff7b72if Tffa657lenTb4b4b4(Te6edf3packetTb4b4b4) Tff7b72> Te6edf3max_payloadTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] packet too large: Tffd700{Tffa657lenTb4b4b4(Te6edf3packetTb4b4b4)Tffd700}Ta5d6ff > Tffd700{Te6edf3max_payloadTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72False
Tff7b72continue
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] TX: Tffd700{Tffa657lenTb4b4b4(Te6edf3packetTb4b4b4)Tffd700}Ta5d6ff bytesTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptt_onTb4b4b4(Tb4b4b4)
T8b949e# For VOX with tone enabled send a short tone to trigger VOX
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_type Tff7b72== Ta5d6ff"Ta5d6ffvoxTa5d6ff" Tff7b72and Tff7b72selfTff7b72.Td2a8ffvox_toneTb4b4b4:
T8b949e# 100ms of 1kHz tone at 8kHz sample rate
Te6edf3tone_duration Tff7b72= T79c0ff0.1
Te6edf3sample_rate Tff7b72= T79c0ff8000
Te6edf3frequency Tff7b72= T79c0ff1000
Te6edf3t Tff7b72= Te6edf3npTff7b72.Td2a8fflinspaceTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3tone_durationTb4b4b4, Tffa657intTb4b4b4(Te6edf3sample_rate Tff7b72* Te6edf3tone_durationTb4b4b4)Tb4b4b4)
Te6edf3tone Tff7b72= Tb4b4b4(Te6edf3npTff7b72.Td2a8ffsinTb4b4b4(T79c0ff2 Tff7b72* Te6edf3npTff7b72.Td2a8ffpi Tff7b72* Te6edf3frequency Tff7b72* Te6edf3tTb4b4b4) Tff7b72* T79c0ff32767 Tff7b72* T79c0ff0.3Tb4b4b4)Tff7b72.Td2a8ffastypeTb4b4b4(Te6edf3npTff7b72.Td2a8ffint16Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffpushTb4b4b4(Te6edf3toneTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3tone_duration Tff7b72+ T79c0ff0.1Tb4b4b4)
Te6edf3tx_audio Tff7b72= Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8fftx_burstTb4b4b4(Te6edf3packetTb4b4b4)
Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffnbuffer Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffpushTb4b4b4(Te6edf3npTff7b72.Td2a8fffrombufferTb4b4b4(Te6edf3tx_audioTb4b4b4, Te6edf3dtypeTff7b72=Te6edf3npTff7b72.Td2a8ffint16Tb4b4b4)Tb4b4b4)
T8b949e# calculate expected time
Te6edf3samples_to_tx Tff7b72= Tffa657lenTb4b4b4(Te6edf3tx_audioTb4b4b4) Tff7b72/Tff7b72/ T79c0ff2 T8b949e# 16-bit samples
Te6edf3expected_time Tff7b72= Te6edf3samples_to_tx Tff7b72/ T79c0ff8000.0 T8b949e# 8kHz sample rate
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3expected_time Tff7b72+ T79c0ff0.5Tb4b4b4)
T8b949e# clear any remaining samples
Tff7b72selfTff7b72.Td2a8fftx_audio_bufferTff7b72.Td2a8ffnbuffer Tff7b72= T79c0ff0
T8b949e# disable PTT
Tff7b72selfTff7b72.Td2a8ffptt_offTb4b4b4(Tb4b4b4)
T8b949e# add PTT tail delay
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptt_tail_delayTb4b4b4)
T8b949e# clear transmitting flag
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72False
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] transmission completeTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Te6edf3queueTff7b72.Td2a8ffEmptyTb4b4b4:
Tff7b72continue
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72False
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffTX error in FreeDV interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72import T7ee787traceback
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Te6edf3tracebackTff7b72.Td2a8ffformat_excTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72def Td2a8ffrx_loopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72while Tff7b72selfTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# get our samples for demodulation
Te6edf3nin Tff7b72= Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffnin
Te6edf3samples Tff7b72= Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffget_samplesTb4b4b4(Te6edf3ninTb4b4b4)
Tff7b72if Te6edf3samples Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrx_audio_bufferTff7b72.Td2a8ffpopTb4b4b4(Te6edf3ninTb4b4b4)
Te6edf3signal_level Tff7b72= Te6edf3npTff7b72.Td2a8ffsqrtTb4b4b4(Te6edf3npTff7b72.Td2a8ffmeanTb4b4b4(Te6edf3samplesTff7b72.Td2a8ffastypeTb4b4b4(Tffa657floatTb4b4b4) Tff7b72*Tff7b72* T79c0ff2Tb4b4b4)Tb4b4b4) Tff7b72/ T79c0ff32768.0
Te6edf3nbytes_outTb4b4b4, Te6edf3rx_bytesTb4b4b4, Te6edf3sync_stateTb4b4b4, Te6edf3snr_value Tff7b72= Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffrxTb4b4b4(Te6edf3samplesTff7b72.Td2a8fftobytesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupdate_channel_stateTb4b4b4(Te6edf3sync_state Tff7b72> T79c0ff0Tb4b4b4, Te6edf3signal_levelTb4b4b4)
Tff7b72if Te6edf3nbytes_out Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] raw RX: Tffd700{Te6edf3nbytes_outTffd700}Ta5d6ff bytesTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
T8b949e# For FreeDV, we get the full frame including CRC
T8b949e# The CRC is the last 2 bytes. but FreeDV already validates it
T8b949e# If were here, the CRC was good, so we can use the payload
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rx_bytesTb4b4b4) Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
T8b949e# remove the CRC (last 2 bytes)
Te6edf3payload Tff7b72= Te6edf3rx_bytesTb4b4b4[Tb4b4b4:Tff7b72-T79c0ff2Tb4b4b4]
Te6edf3actual_length Tff7b72= Tffa657lenTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72while Te6edf3actual_length Tff7b72> T79c0ff0 Tff7b72and Te6edf3payloadTb4b4b4[Te6edf3actual_length Tff7b72- T79c0ff1Tb4b4b4] Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3actual_length Tff7b72-Tff7b72= T79c0ff1
Tff7b72if Te6edf3actual_length Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3packet Tff7b72= Te6edf3payloadTb4b4b4[Tb4b4b4:Te6edf3actual_lengthTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffprocess_incomingTb4b4b4(Tffa657bytesTb4b4b4(Te6edf3packetTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] processed Tffd700{Tffa657lenTb4b4b4(Te6edf3packetTb4b4b4)Tffd700}Ta5d6ff byte packetTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] received empty/padding-only frameTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDVTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# no samples available, sleep a bit and update channel state
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.01Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupdate_channel_stateTb4b4b4(Tff7b72FalseTb4b4b4, Tff7b72selfTff7b72.Td2a8ffrecent_signal_level Tff7b72* T79c0ff0.95Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffRX error in FreeDV interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72def Td2a8ffprocess_incomingTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrxb Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] received Tffd700{Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tffd700}Ta5d6ff byte packet (total: Tffd700{Tff7b72selfTff7b72.Td2a8ffrxbTffd700}Ta5d6ff bytes)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffownerTff7b72.Td2a8ffinboundTb4b4b4(Te6edf3dataTb4b4b4, Tff7b72selfTb4b4b4)
Tff7b72def Td2a8ffprocess_outgoingTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffonlineTb4b4b4:
Te6edf3max_payload Tff7b72= Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffpayload_bytes_per_modem_frame
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72> Te6edf3max_payloadTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
T8b949e# Add packet to queue - it will be sent when channel is clear
Tff7b72selfTff7b72.Td2a8fftx_queueTff7b72.Td2a8ffputTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff1.0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fftxb Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffcsma_enabled Tff7b72and Tff7b72selfTff7b72.Td2a8ffchannel_busy Tff7b72and Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffFreeDV [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] queued packet #Tffd700{Tff7b72selfTff7b72.Td2a8fftx_queueTff7b72.Td2a8ffqsizeTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff, will send when channel is clearTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72except Te6edf3queueTff7b72.Td2a8ffFullTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffTX queue full on FreeDV interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff]Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4)
Tff7b72def Td2a8ffshould_ingress_limitTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffget_hashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72import T7ee787hashlib
Tff7b72return Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDVInterface.Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff"Tff7b72.Td2a8ffencodeTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72.Td2a8ffdigestTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffcloseTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffonline Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72False
T8b949e# Ckear any pending transmissions
Tff7b72selfTff7b72.Td2a8ffis_transmitting Tff7b72= Tff7b72False
Tff7b72if Tff7b72selfTff7b72.Td2a8fftx_threadTb4b4b4:
Tff7b72selfTff7b72.Td2a8fftx_threadTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrx_threadTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrx_threadTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffmonitor_threadTa5d6ff'Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffmonitor_threadTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmonitor_threadTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffstreamTa5d6ff'Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffstreamTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffis_activeTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffstop_streamTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstreamTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72exceptTb4b4b4:
Tff7b72pass
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffpTa5d6ff'Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6fffreedvTa5d6ff'Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fffreedvTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffptt_serialTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffptt_serialTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdebugTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFreeDV Interface [Tffd700{Tff7b72selfTff7b72.Td2a8ffnameTffd700}Ta5d6ff] closedTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
T8b949e# Register
Te6edf3interface_class Tff7b72= Te6edf3FreeDVInterface
T8b949e# Helper script to list audio devices and hamlib radios when run directly
Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Tff7b72import T7ee787sys
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFreeDV Interface for ReticulumTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff" Tff7b72* T79c0ff60Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffAvailable audio devices:Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff-Ta5d6ff" Tff7b72* T79c0ff50Tb4b4b4)
Te6edf3p Tff7b72= Te6edf3pyaudioTff7b72.Td2a8ffPyAudioTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3pTff7b72.Td2a8ffget_device_countTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3info Tff7b72= Te6edf3pTff7b72.Td2a8ffget_device_info_by_indexTb4b4b4(Te6edf3iTb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDevice Tffd700{Te6edf3iTffd700}Ta5d6ff: Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffnameTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Channels: Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxInputChannelsTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff in, Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffmaxOutputChannelsTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff outTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Sample Rate: Tffd700{Te6edf3infoTb4b4b4[Ta5d6ff'Ta5d6ffdefaultSampleRateTa5d6ff'Tb4b4b4]Tffd700}Ta5d6ff"Tb4b4b4)
Te6edf3pTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ffrigctlTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff--listTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4, Te6edf3textTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72exceptTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffrigctl not found - install hamlib for radio control (view README for install instructions)Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffConfiguration examples:Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff-Ta5d6ff" Tff7b72* T79c0ff50Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"""
Ta5d6ff [[FreeDV with IC-7300]]
Ta5d6ff type = FreeDVInterface
Ta5d6ff enabled = yes
Ta5d6ff input_device = default
Ta5d6ff output_device = default
Ta5d6ff freedv_mode = datac1
Ta5d6ff ptt_type = hamlib
Ta5d6ff hamlib_model = 3073 # run rigctl -l to list devices
Ta5d6ff hamlib_device = /dev/ttyUSB0
Ta5d6ff hamlib_speed = 19200
Ta5d6ff Ta5d6ff"""Tb4b4b4)
Served by rngit 1.5.2 - Generated in 0.09s